/*
 * Copyright (c) 2010 Mathew Hall, University of Sheffield.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following conditions
 * are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided
 * with the distribution.
 *
 * Neither the name of the University of Sheffield nor the names of its
 * contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
package primitives.cluster;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import primitives.graph.Node;

/**
 * Leaf of clustering tree - stores list of nodes in this partition.
 * @author mat
 */
public class ClusterLeaf  implements IClusterLevel, Serializable{
	//XXX: NOOOOOO! Had to change this again.
	private static final long serialVersionUID = 0xBEEFB00C; //-3881436014264360147L;//-3238039936487263L;
	
	private Node node;
	private Set<Integer> id;
	
	
	

	public void setId(int id) {
		this.id.add(id);
//		this.id.remove(-1);
	}
	
	public List<ClusterLeaf> getLeaves(){
		ArrayList<ClusterLeaf> ret = new ArrayList<ClusterLeaf>();
		ret.add(this);
		return ret;
	}

	public ClusterLeaf deepCopy(){
		ClusterLeaf newMe = new ClusterLeaf();

		newMe.node = node.clone();

		for(Integer i : id){
			newMe.setID(i);
		}
		return newMe;
	}
	
	/**
	 * 
	 * @return a HashSet of one element containing the node stored in this leaf.
	 */
	public Set<Node> getNodes(){
		HashSet<Node> temp = new HashSet<Node>();
		temp.add(node);
		return temp;
	}
	
	public void getNodes(Set<Node> to){
		to.add(node);
	}
	
	/**
	 * Get the size of the leaf. Leaves only store between 0 and 1 objects
	 * @return 1 if this leaf contains a node.
	 */
	public int getSize(){
		return (node==null)?0:1;
	}
	
	@Override
	public String toString() {
		 return String.format("\n\tClusterLeaf\t{%s}",node);



	}

	public ClusterLeaf(){
		node = new Node();
		id = new HashSet<Integer>();
		id.add(-1);
	}
	
	public void addNode(Node n){
		node = n;
	}
	
	public boolean encapsulates(){  return false; }


	
	public boolean contains(Node n){
		 return node.equals(n);
	}
	
	public boolean knownAs(int i){
		 return id.contains(i);
	}
	
	/**
	 * Determines if a node x in this cluster exists such that x -> n
	 * @param n the node to search for connectivity to
	 * @ return true if there is an edge between a node in this cluster and the parameter
	 */
	public boolean connectivityTo(Node n){

		if(node.getTransitionsAsN().contains(n)) return true;
		return false;
	}
	
	/**
	 * Determines if a node x in this cluster exists such that n -> x
	 * @param n the node to search for connectivity from
	 * @ return true if there is an edge between the parameter and this cluster
	 */
	public boolean connectivityFrom(Node n){
		for(Node a : n.getTransitionsAsN())
			if(node.equals(a)) return true;
		 return false;
		
		
	}
	/**
	 * Determines if a node has a transition between this cluster in either direction.
	 * @param n the node to search for connectivity with
	 * @ return true if there is an edge between this cluster and the parameter.
	 */
	public boolean connectivityBidir(Node n){
		 return connectivityFrom(n) || connectivityTo(n);
	
	}
	
	public ClusterLeaf getCluster(){
		 return this;
	}

	public Set<Integer> getIDs(){
             return id;
            // return new HashSet<Integer>(id);
                //HashSet<Integer> copy = (HashSet<Integer>)id;
                // return (Set<Integer>)(copy.clone());
	}

	/* TODO: does this method even get used in ClusterLeaf? */
	public void setID(int i){
		id.add(i);
//		id.remove(-1);
	}
}
